package main.controller;

import com.mongodb.BasicDBObject;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import main.*;
import main.database.*;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

@Controller
public class ArticlePageController {

    @RequestMapping(value = "/fiction/{id}")
    public String fictionPage(HttpServletRequest request, @PathVariable(value="id") String id, ModelMap modelMap) {
        String uuid = RequestHelper.getUserUUIDFromRequest(request);
        String account = AccountHelper.getAccountInfoFromUUID(uuid);
        boolean isLogin = true;
        if (account == null || account.isEmpty()) {
            isLogin = false;
        }

        String user = "";
        if (isLogin) {
            user = uuid;
        }

        boolean isAdmin = AccountHelper.isAdminFromUUID(uuid);
        StatisticHelper.addArticlePageAccess(uuid, NetworkHelper.getIPAddress(request), TimeHelper.getFormattedNowString(), UserAgentHelper.getUserAgent(request));

        boolean isCrawler = UserAgentHelper.isCrawlFromRequestInfo(request);
        if (isCrawler) {
            Logman.info("isCrawler");
            return "articlenotfound";
        }
        else {
            MongoCollection<Document> collection = DatabaseMan.Instance().GetCollection(GlobalConfig.collectionNameOfArticle);
            FindIterable<Document> findIterable = collection.find(new BasicDBObject("_id", new ObjectId(id)));
            MongoCursor<Document> cursor = findIterable.iterator();

            String targetPage = "fictionPage";
            if (cursor.hasNext()) {
                // article self
                Document doc = cursor.next();

                String title = (String) doc.get("title");
                String description = (String) doc.get("description");
                String catlog = (String) doc.get("catlog");
                String authorId = (String) doc.get("author");
                String author = AuthorHelper.getAuthorNameFromId(authorId);
                String fictionId = doc.get("_id").toString();
                String finishYear = (String) doc.get("finishyear");
                double dScore = (Double) doc.get("score");
                String strScore = ScoreHelper.getFormattedSecretScore(dScore);
                Long scoredCount = (Long) doc.get("scoredcount");

                String authorUrl = "#";
                if (authorId != null) {
                    authorUrl = "/author/" + authorId;
                }

                boolean collected = false;
                if (uuid == null || uuid.isEmpty()) {
                    collected = false;
                } else {
                    collected = CollectionHelper.checkUserCollection(uuid, id);
                }

                // discussion content
                List<List<String>> discussionList = DiscussionHelper.getDiscussionOfArticle(id, uuid);

                // author has other articles
                List<String[]> artileList = AuthorHelper.getAuthorArticleList(authorId);
                List<String[]> artileListExcludeThis = excludeArtile(artileList, id);

                // interest list
                List<String[]> interests = ArticleHelper.getRandomCountArticles(8);

                // choicest list
                List<String[]> choicest = ArticleHelper.getSameCatlogAndScoreAbove(catlog, dScore, fictionId);

                // has audio version
                List<String[]> audioInfos = AudioHelper.getAudioInfoFromArticleId(id);

                // has movie version
                List<String[]> movieInfos = MovieHelper.getMovieInfoFromArticleId(id);

                long unread = NotifyHelper.countUnreadNotify(uuid);

                boolean isScoreValid = true;
                if (scoredCount < GlobalConfig.getMinimumVote()) {
                    isScoreValid = false;
                }

                String baseUrl = UriHelper.getServerBaseUri(request);
                double myScore = ScoreHelper.getUserScore(uuid, fictionId);

                modelMap.put("siteName", GlobalConfig.siteName);
                modelMap.put("serverUri", baseUrl);
                modelMap.put("title", title);
                modelMap.put("description", description);
                modelMap.put("catlog", catlog);
                modelMap.put("author", author);
                modelMap.put("authorLink", authorUrl);
                modelMap.put("isScoreValid", isScoreValid);
                if (isScoreValid) {
                    modelMap.put("score", strScore);
                } else {
                    Long voteDiff = GlobalConfig.getMinimumVote() - scoredCount;
                    modelMap.put("voteDiff", voteDiff);
                }
                modelMap.put("collected", collected);
                modelMap.put("fictionid", fictionId);
                modelMap.put("finishyear", finishYear);
                modelMap.put("isLogin", isLogin);
                modelMap.put("isAdmin", isAdmin);
                modelMap.put("discussionList", discussionList);
                modelMap.put("messageCount", discussionList.size());
                modelMap.put("otherArticleList", artileListExcludeThis);
                modelMap.put("maybeInterest", interests);
                modelMap.put("choicest", choicest);
                modelMap.put("audioInfos", audioInfos);
                modelMap.put("movieInfos", movieInfos);
                modelMap.put("unread", unread);
                modelMap.put("myScore", myScore);
                modelMap.put("year2year", TimeHelper.getFormattedYear2Year());
                if (isLogin) {
                    modelMap.put("userId", uuid);
                }
            } else {
                //TODO: better solution for none find article
                Logman.info("数据库中找不到文章");
                targetPage = "/articlenotfound";
            }
            cursor.close();

            return targetPage;
        }
    }

    @RequestMapping(value = "/articlenotfound")
    public String articleNotFound(HttpServletRequest request) {
        return "articleNotFound";
    }

    private List<String[]> excludeArtile(List<String[]> list, String exceptThis) {
        List<String[]> resultList = new ArrayList<>();
        for (int i = 0; i < list.size(); ++i) {
            if (!list.get(i)[0].equals(exceptThis)) {
                resultList.add(list.get(i));
            }
        }

        return resultList;
    }
}
